﻿#include "cmainframe.h"

#if defined (WIN32)
#include "CrashRpt.h"
#endif

#include "serversettingsdialog.h"
#include "scriptmanager.h"
#include "nodemanager/wnodemanager.h"
#include "cjson.h"
#include "resources/logo.xpm"

initialiseSingleton(CMainFrame);

BEGIN_EVENT_TABLE( CMainFrame, wxFrame )
    EVT_CLOSE(CMainFrame::OnClose)
END_EVENT_TABLE()

CMainFrame::CMainFrame(const wxString& title,
                       const wxPoint& pos,
                       const wxSize& size)
    : wxFrame(nullptr, wxID_ANY, title,pos,size)
{
    SetIcon(wxIcon(logo_xpm));

    // 初始化日志系统
    ILog4zManager::getInstance()->start();

    // 主日志器配置
    ILog4zManager::getInstance()->setLoggerPath(LOG4Z_MAIN_LOGGER_ID, "./ss_logs");
    ILog4zManager::getInstance()->setLoggerOutFile(LOG4Z_MAIN_LOGGER_ID, true);
    //ILog4zManager::getInstance()->setLoggerFileMaxSize(LOG4Z_MAIN_LOGGER_ID, 50 * 1024 * 1024); // 50MB
    ILog4zManager::getInstance()->setLoggerLevel(LOG4Z_MAIN_LOGGER_ID, LOG_LEVEL_DEBUG);

#if defined (WIN32)
    wxString crashreportpath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"\\CrashReports";

    CR_INSTALL_INFO info;
    memset(&info, 0, sizeof(CR_INSTALL_INFO));
    info.cb = sizeof(CR_INSTALL_INFO);             // Size of the structure
    info.pszAppName = _T("信号模拟器"); // App name
    info.pszAppVersion = _T("1.0.0");              // App version
    //info.pszEmailSubject = _T("股道自动化管理系统故障报告"); // Email subject
    //info.pszEmailTo = _T("test@hotmail.com");      // Email recipient address
    info.pszErrorReportSaveDir = crashreportpath.ToStdWstring().c_str(); // 崩溃报告保存目录
    info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;
    info.dwFlags |= CR_INST_DONT_SEND_REPORT;
    //把Dump压缩成zip文件
    info.dwFlags |= CR_INST_STORE_ZIP_ARCHIVES;
    info.dwFlags |= CR_INST_AUTO_THREAD_HANDLERS;
    info.uMiniDumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory);
                                                   // Install crash handlers
    int nInstResult = crInstall(&info);

    // Check result
    if (nInstResult != 0)
    {
        TCHAR buff[256];
        crGetLastErrorMsg(buff, 256); // Get last error
        //LOGE(buff);
    }
#endif

    Bind(wxEVT_CHAR_HOOK, &CMainFrame::OnKeyDown, this);
    Bind(DRAPLIST_SELECTED_EVENT, &CMainFrame::OnDrapListSelectedEvent, this);

    new WSignalServer();

    // 创建 AUI 管理器
    m_auimgr.SetManagedWindow(this);
    m_auimgr.SetFlags(wxAUI_MGR_DEFAULT);

    wxPanel *pmainPanel = new wxPanel(this);
    //psystemlogtextPanel->SetMinSize(wxSize(300,30));
    wxBoxSizer* pmainPanelsizer = new wxBoxSizer(wxHORIZONTAL);
    wxNotebook *pnotebook = new wxNotebook(pmainPanel, wxID_ANY,
                                           wxDefaultPosition, wxDefaultSize,
                                           wxNB_LEFT);

    wxImageList* imageList = new wxImageList(16, 16);
    imageList->Add(wxArtProvider::GetBitmap(wxART_HELP_BOOK, wxART_OTHER, wxSize(16, 16)));
    imageList->Add(wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_OTHER, wxSize(16, 16)));
    imageList->Add(wxArtProvider::GetBitmap(wxART_HELP_PAGE, wxART_OTHER, wxSize(16, 16)));
    pnotebook->SetImageList(imageList);

    // 添加页面
    m_pSwitchDropDownListPanel = new DropDownListPanel(pnotebook,wxT("道岔"));
    m_pSignalDropDownListPanel = new DropDownListPanel(pnotebook,wxT("信号灯"));
    m_pSectDropDownListPanel = new DropDownListPanel(pnotebook,wxT("轨道区段"));

    int pageIndex = pnotebook->GetPageCount();
    pnotebook->AddPage(m_pSwitchDropDownListPanel, wxT("道岔"), true);  // 第三个参数表示是否默认选中
    pnotebook->SetPageImage(pageIndex, 0);
    pageIndex = pnotebook->GetPageCount();
    pnotebook->AddPage(m_pSignalDropDownListPanel, wxT("信号灯"));
    pnotebook->SetPageImage(pageIndex, 1);
    pageIndex = pnotebook->GetPageCount();
    pnotebook->AddPage(m_pSectDropDownListPanel, wxT("轨道区段"));
    pnotebook->SetPageImage(pageIndex, 2);

    pmainPanelsizer->Add(pnotebook,  1, wxEXPAND | wxALL, 0);
    pmainPanel->SetSizer(pmainPanelsizer);

    wxPanel *psystemlogtextPanel = new wxPanel(this);
    //psystemlogtextPanel->SetMinSize(wxSize(300,30));
    wxBoxSizer* systemlogtextPanelsizer = new wxBoxSizer(wxHORIZONTAL);

    m_systemlogtextCtrl = new wxRichTextCtrl(psystemlogtextPanel, wxID_ANY,
                                        wxT(""),
                                        wxDefaultPosition, wxDefaultSize,
                                        wxTE_MULTILINE|wxTE_READONLY);

    systemlogtextPanelsizer->Add(m_systemlogtextCtrl,  1, wxEXPAND | wxALL, 0);
    psystemlogtextPanel->SetSizer(systemlogtextPanelsizer);

    wxPanel *pscriptEditPanel = new wxPanel(this);
    wxBoxSizer* scriptEditPanelsizer = new wxBoxSizer(wxHORIZONTAL);

    m_MainScriptEditor = new MainScriptEditor(pscriptEditPanel,wxID_ANY);

    scriptEditPanelsizer->Add(m_MainScriptEditor,  1, wxEXPAND | wxALL, 0);
    pscriptEditPanel->SetSizer(scriptEditPanelsizer);

    m_auimgr.AddPane(pmainPanel, wxAuiPaneInfo().
                 Name(wxT("主面板")).Caption(wxT("主面板")).
                 CenterPane());
    m_auimgr.AddPane(psystemlogtextPanel, wxAuiPaneInfo()
                  .Name(wxT("日志输出面板"))
                  .Caption(wxT("日志输出面板"))
                  .Bottom()
                  .Layer(0)
                  .MinSize(600, 150)
                  .CloseButton(true));
    m_auimgr.AddPane(pscriptEditPanel, wxAuiPaneInfo()
                  .Name(wxT("脚本编辑面板"))
                  .Caption(wxT("脚本编辑面板"))
                  .CaptionVisible(false)  // 隐藏标题栏
                  .Right()
                  .Layer(1)
                  .MinSize(450, -1)
                  .CloseButton(false));

    // 更新 AUI 管理器
    m_auimgr.Update();

    // 1. 创建菜单栏
    wxMenuBar *menuBar = new wxMenuBar();

    // 2. 创建设置菜单
    wxMenu *setMenu = new wxMenu();
    wxMenuItem* signalserverItem = new wxMenuItem(setMenu, IDD_MENU_SIGNALSERVER_SET,
                                                wxT("信号服务器设置"),
                                                wxT("用于设置信号服务器参数."));
    signalserverItem->SetBitmap(wxArtProvider::GetBitmap(wxART_HELP_SIDE_PANEL, wxART_MENU));
    setMenu->Append(signalserverItem);

    // 将菜单添加到菜单栏
    menuBar->Append(setMenu, wxT("&设置"));

    // 设置菜单栏到框架
    SetMenuBar(menuBar);

    // 统一绑定到同一个处理函数
    Bind(wxEVT_MENU,
         &CMainFrame::OnMainFrameMenu,
         this,
         IDD_MENU_SIGNALSERVER_SET);

    // 初始化网络系统
    WSignalServer::getSingleton().setNetworkFrameManager(this);

    // 结点管理系统
    new CRouteConditions();
    new WNodeManager();

    // 初始化日志系统
    new ScriptManager();
    ScriptManager::getSingleton().lua_init();

    // 注册类到lua
    ScriptManager::getSingleton().registertoLua();

    m_sysInitTimer = new wxTimer(this, wxID_ANY);
    m_sysInitTimer->StartOnce(100);
    this->Bind(wxEVT_TIMER, &CMainFrame::OnSystemInitTimer,
               this,m_sysInitTimer->GetId());
    m_scriptTimer = new wxTimer(this, wxID_ANY+1);
    this->Bind(wxEVT_TIMER, &CMainFrame::OnSystemScriptTimer,
               this,m_scriptTimer->GetId());
    m_scriptTimer->Start(1000);

    this->CenterOnScreen();
}

CMainFrame::~CMainFrame()
{
    ScriptManager::getSingleton().lua_exit();
    delete CRouteConditions::getSingletonPtr();
    delete ScriptManager::getSingletonPtr();
    delete WNodeManager::getSingletonPtr();
    delete WSignalServer::getSingletonPtr();

    delete m_sysInitTimer;
    m_sysInitTimer = NULL;
    delete m_scriptTimer;
    m_scriptTimer = NULL;

    m_auimgr.UnInit();

#if defined (WIN32)
    crUninstall();
#endif
}

void CMainFrame::OnSystemScriptTimer(wxTimerEvent& event)
{
    this->onProcessAllTimerEvent();
}

void CMainFrame::OnSystemInitTimer(wxTimerEvent& event)
{
    // 获取当前程序脚本的完整路径
    wxString m_curScriptWorkingPath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/resources/scripts";

    // 导入脚本并执行
    if(!ScriptManager::getSingleton().exe_lua_string_for_path(m_curScriptWorkingPath))
        return;

    m_curScriptWorkingPath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/resources/simulator/main.lua";

    // 导入main.lua并执行
    if(!ScriptManager::getSingleton().exe_lua_string_for_file(m_curScriptWorkingPath))
        return;

    m_MainScriptEditor->LoadFile(m_curScriptWorkingPath);

    // 注册主窗口到系统中
    ScriptManager::getSingleton().registerMainFrametoLua(this);

    // 注册结点管理系统
    ScriptManager::getSingleton().registerNodeManagertoLua(WNodeManager::getSingletonPtr());

    // 调用lua初始函数
    ScriptManager::getSingleton().callLuaFunctionWithSystemInit();

    std::map<wxString,tagSectNode*> allSects = WNodeManager::getSingleton().getAllSects();
    if(allSects.empty())
        return;

    std::map<wxString,tagSectNode*>::iterator itersect = allSects.begin();
    for(;itersect != allSects.end();++itersect)
    {
        wxArrayString states;
        states.Add(wxT("出清"));
        states.Add(wxT("占用"));
        m_pSectDropDownListPanel->addLabeledComboBox(new LabeledComboBox(m_pSectDropDownListPanel,
                                                                         (*itersect).first,
                                                                         states));
    }

    std::map<wxString,WBaseNode*> allnodes = WNodeManager::getSingleton().getAllNodes();
    if(allnodes.empty())
        return;

    std::map<wxString,WBaseNode*>::iterator iter = allnodes.begin();
    for(;iter != allnodes.end();++iter)
    {
        switch((*iter).second->getNodeType())
        {
        case NODE_SWITCH:
        {
            WSwitchNode *pSwitchNode = static_cast<WSwitchNode*>((*iter).second);
            if(pSwitchNode)
            {
                wxArrayString states;
                states.Add(wxT("定位"));
                states.Add(wxT("反位"));
                states.Add(wxT("无信号"));

                LabeledComboBox *pLabeledComboBox = new LabeledComboBox(m_pSwitchDropDownListPanel,
                                                                        (*iter).second->getName(),
                                                                        states);
                pLabeledComboBox->GetComboBox()->SetSelection(pSwitchNode->getSwitchState());

                m_pSwitchDropDownListPanel->addLabeledComboBox(pLabeledComboBox);
            }
        }
            break;
        case NODE_SIGNAL:
        {
            wxArrayString states;
            states.Add(wxT("蓝灯"));
            states.Add(wxT("白灯"));
            m_pSignalDropDownListPanel->addLabeledComboBox(new LabeledComboBox(m_pSignalDropDownListPanel,
                                                                               (*iter).second->getName(),
                                                                               states));
        }
            break;
        default:
            break;
        }
    }

    wxFileConfig config(IDD_APPLICTION_NAME);
    int serverport = 0;
    wxString serverip = config.Read("signalserverip");
    config.Read("signalserverport",&serverport);

    if(serverip != "" && serverport > 0)
    {
        if(WSignalServer::getSingleton().setServerParams(serverip,serverport))
            WSignalServer::getSingleton().Open();
    }
}

/// 打印日志
void CMainFrame::printlog(int level,const char* str,bool issave)
{
    if(str == "" || m_systemlogtextCtrl == NULL) return;

    wxCSConv gb2312Conv(wxFONTENCODING_UTF8);
    wxString decStr(str, gb2312Conv);

    if(m_systemlogtextCtrl->GetNumberOfLines() > 2000)
        m_systemlogtextCtrl->Clear();

    wxRichTextAttr colText;
    colText.SetTextColour(*wxBLACK);

    if(level > LOG_LEVEL_INFO)
        colText.SetTextColour(*wxRED);

    wxString formatted1 = wxDateTime::Now().Format("[%Y-%m-%d %H:%M:%S] ");

    m_systemlogtextCtrl->BeginStyle(colText);
    m_systemlogtextCtrl->AppendText(formatted1 + decStr + "\n");
    m_systemlogtextCtrl->EndStyle();

    // 获取最后一行位置
    long lastPos = m_systemlogtextCtrl->GetLastPosition();

    // 滚动到末尾（确保可见）
    m_systemlogtextCtrl->ScrollIntoView(lastPos, WXK_END);
    m_systemlogtextCtrl->ShowPosition(lastPos);

    if(issave)
        LOG_STREAM(LOG4Z_MAIN_LOGGER_ID,level,str);
}

void CMainFrame::OnClose(wxCloseEvent& event)
{
    // 弹出确认对话框
    wxMessageDialog dialog(
        this,
        wxT("您是否要退出系统?"),
        wxT("退出确认"),
        wxYES_NO | wxICON_QUESTION | wxICON_WARNING
    );

    if (dialog.ShowModal() == wxID_YES)
    {
        m_MainScriptEditor->SaveFile();
        event.Skip();
    } else {
        event.Veto();
    }
}

void CMainFrame::OnKeyDown(wxKeyEvent& event)
{
    int keyCode = event.GetKeyCode();

    switch(keyCode) {
    case WXK_F9:
    {
        if(m_MainScriptEditor->SaveFile())
        {
            wxString pcurScriptWorkingPath = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()+"/resources/simulator/main.lua";

            // 导入main.lua并执行
            if(ScriptManager::getSingleton().exe_lua_string_for_file(pcurScriptWorkingPath))
            {
                printlog(LOG_LEVEL_INFO,"脚本保存并加载成功.");

                wxFileConfig config(IDD_APPLICTION_NAME);
                int serverport = 0;
                wxString serverip = config.Read("signalserverip");
                config.Read("signalserverport",&serverport);

                if(serverip != "" && serverport > 0)
                {
                    if(WSignalServer::getSingleton().setServerParams(serverip,serverport))
                        WSignalServer::getSingleton().Open();
                }
            }
            else
                printlog(LOG_LEVEL_ERROR,"脚本加载失败.");
        }
    }
        break;
    default:
        break;
    }

    event.Skip();
}

void CMainFrame::OnMainFrameMenu(wxCommandEvent& event)
{
    switch(event.GetId())
    {
    case IDD_MENU_SIGNALSERVER_SET:
    {
        wxFileConfig config(IDD_APPLICTION_NAME);
        int serverport = 0;
        wxString serverip = config.Read("signalserverip");
        config.Read("signalserverport",&serverport);

        // 创建并显示对话框
        ServerSettingsDialog dlg(this,
                                 wxT("服务器设置"));
        dlg.SetSignalServerParams(serverip.empty() ? wxT("127.0.0.1") : serverip,
                                  serverport <= 0 ? 8888 : serverport);
        if (dlg.ShowModal() == wxID_OK)
        {
            config.Write("signalserverip",dlg.GetSignalServerIP());
            config.Write("signalserverport",dlg.GetSignalServerPort());

            if(WSignalServer::getSingleton().setServerParams(dlg.GetSignalServerIP(),
                                               dlg.GetSignalServerPort()))
                WSignalServer::getSingleton().Open();
        }
    }
        break;
    default:
        break;
    }
}

void CMainFrame::OnDrapListSelectedEvent(wxThreadEvent& event)
{
    if(event.GetString().IsEmpty())
        return;

    wxScopedCharBuffer decData = event.GetString().ToUTF8();
    this->sendSignals(IDD_NETWORK_MSG_SIGNAL_COLLECT,decData.data(),decData.length());
}

/// 得到所有的信号
wxString CMainFrame::getSignals(wxVector<wxString> nodes)
{
    wxString signalMsg = wxString::Format("[%s,%s,%s]",
                            m_pSwitchDropDownListPanel->getParams(nodes),
                            m_pSignalDropDownListPanel->getParams(nodes),
                            m_pSectDropDownListPanel->getParams(nodes));

    return signalMsg;
}

/// 发送信息到服务器
void CMainFrame::sendSignals2(int msgId,wxString signalMsg,const char* clientid)
{
    if(signalMsg == "") return;

    wxScopedCharBuffer decData = signalMsg.ToUTF8();
    this->sendSignals(msgId,decData.data(),decData.length(),clientid);
}

/// 发送信息到服务器
void CMainFrame::sendSignals(int msgId,const char* signalMsg,int msglength,const char* clientid)
{
    if(msgId <= 0 || signalMsg == "") return;

    wxString decSendMsg = wxString::FromUTF8((const char*)signalMsg,msglength);
    printlog(LOG_LEVEL_INFO,
             wxString::Format(wxT("发送信号:%s"),decSendMsg).ToUTF8());

    wxScopedCharBuffer decMsg = decSendMsg.ToUTF8();
    WSignalServer::getSingleton().SendData(msgId,
                            decMsg.data(),
                            decMsg.length(),
                            clientid);
}

/// 更新所有的信息
bool CMainFrame::updateSignals(const char* clientid,const char* signalMsg,int msglength)
{
    if(signalMsg == "" || clientid == NULL) return false;

    wxString desMessage = wxString::FromUTF8((const char*)signalMsg,msglength);

    printlog(LOG_LEVEL_INFO,
             wxString::Format(wxT("改变信号:%s:%s"),clientid,desMessage).ToUTF8().data());

    // 解析JSON字符串
    cJSON *root = cJSON_Parse(desMessage.ToUTF8().data());
    if (root == NULL) {
        printlog(LOG_LEVEL_ERROR,cJSON_GetErrorPtr());
        return false;
    }

    /*cJSON *signal = cJSON_GetObjectItem(root, "signal");
    if (signal != NULL)
    {
        // 解析"道岔"数组
        cJSON *daocha = cJSON_GetObjectItemCaseSensitive(signal, "道岔");
        if (cJSON_IsArray(daocha)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, daocha) {
                cJSON *child = item->child;
                while (child) {
                    WBaseNode *pBaseNode = WNodeManager::getSingleton().getNodeByDeviceID(atoi(child->string));
                    m_pSwitchDropDownListPanel->setParams(pBaseNode == NULL ? wxString::FromUTF8(child->string) : pBaseNode->getName(), wxString::FromUTF8(child->valuestring));
                    child = child->next;
                }
            }
        }

        // 解析"信号灯"数组
        cJSON *signal_lights = cJSON_GetObjectItemCaseSensitive(signal, "信号灯");
        if (cJSON_IsArray(signal_lights)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, signal_lights) {
                cJSON *child = item->child;
                while (child) {
                    WBaseNode *pBaseNode = WNodeManager::getSingleton().getNodeByDeviceID(atoi(child->string));
                    m_pSignalDropDownListPanel->setParams(pBaseNode == NULL ? wxString::FromUTF8(child->string) : pBaseNode->getName(), wxString::FromUTF8(child->valuestring));
                    child = child->next;
                }
            }
        }

        // 解析"轨道区段"数组
        cJSON *track_sections = cJSON_GetObjectItemCaseSensitive(signal, "轨道区段");
        if (cJSON_IsArray(track_sections)) {
            cJSON *item = NULL;
            cJSON_ArrayForEach(item, track_sections) {
                cJSON *child = item->child;
                while (child) {
                    tagSectNode *pSectNode = WNodeManager::getSingleton().getSectByDeviceID(atoi(child->string));
                    m_pSectDropDownListPanel->setParams(pSectNode == NULL ? wxString::FromUTF8(child->string) : pSectNode->sectname, wxString::FromUTF8(child->valuestring));
                    child = child->next;
                }
            }
        }
    }*/

    cJSON *signal = cJSON_GetObjectItem(root, "signal");
    if (signal != NULL)
    {
        // 遍历数组
        cJSON *item = NULL;
        cJSON_ArrayForEach(item, signal) {
            if (cJSON_IsObject(item)) {
                // 获取对象中的第一个键值对
                cJSON *child = item->child;
                int key = atoi(child->string);
                int value = child->valueint;

                WBaseNode *pBaseNode = WNodeManager::getSingleton().getNodeByDeviceID(key);
                if(pBaseNode != NULL)
                {
                    switch(pBaseNode->getNodeType())
                    {
                    case NodeType::NODE_SWITCH:
                    {
                        SwitchState decValue = (SwitchState)value;
                        wxString tmpStr = wxT("无信号");

                        if(decValue == SwitchState::POSITIVE) tmpStr = wxT("定位");
                        else if(decValue == SwitchState::NEGATIVE) tmpStr = wxT("反位");

                        m_pSwitchDropDownListPanel->setParams(pBaseNode->getName(), tmpStr);
                    }
                    break;
                    case NodeType::NODE_SIGNAL:
                    {
                        NodeSignalState decValue = (NodeSignalState)value;
                        wxString tmpStr = wxT("无信号");

                        if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("白灯");
                        else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("蓝灯");

                        m_pSignalDropDownListPanel->setParams(pBaseNode->getName(), tmpStr);
                    }
                    break;
                    default:
                        break;
                    }
                }

                tagSectNode *pSectNode = WNodeManager::getSingleton().getSectByDeviceID(key);
                if(pSectNode != NULL)
                {
                    NodeSignalState decValue = (NodeSignalState)value;
                    wxString tmpStr = wxT("无信号");

                    if(decValue == NodeSignalState::OCCUPY) tmpStr = wxT("占用");
                    else if(decValue == NodeSignalState::CLEAR) tmpStr = wxT("出清");

                    m_pSectDropDownListPanel->setParams(pBaseNode->getName(), tmpStr);
                }
            }
        }
    }

    // 释放内存
    cJSON_Delete(root);

    wxString signalMsgTo = this->getSignals(wxVector<wxString>());
    printlog(LOG_LEVEL_INFO,
             wxString::Format(wxT("发送信号:%s"),signalMsgTo).ToUTF8());

    wxScopedCharBuffer decMsg = signalMsgTo.ToUTF8();
    WSignalServer::getSingleton().SendDataOther(IDD_NETWORK_MSG_SIGNAL_COLLECT,
                            decMsg.data(),
                            decMsg.length(),
                            clientid);

    return true;
}

/// 开始定时器
void CMainFrame::startTimer(wxString name,int interval,
                               int runCount,luabridge::LuaRef pcallback)
{
    wxMutexLocker locker(m_TimerMutex);

    m_TimerItems[name] = tagTimerItem(name,runCount,interval,pcallback);
}

/// 停止指定定时器
void CMainFrame::stopTimer(wxString name)
{
    wxMutexLocker locker(m_TimerMutex);

    std::map<wxString,tagTimerItem>::iterator iter = m_TimerItems.find(name);
    if(iter != m_TimerItems.end())
        m_TimerItems.erase(iter);
}

/// 停止所有定时器
void CMainFrame::stopAllTimer(void)
{
    wxMutexLocker locker(m_TimerMutex);

    m_TimerItems.clear();
}

/// 处理所有定时器事件
void CMainFrame::onProcessAllTimerEvent(void)
{
    if(m_TimerItems.empty())
        return;

    wxMutexLocker locker(m_TimerMutex);

    std::map<wxString,tagTimerItem>::iterator iter = m_TimerItems.begin();
    for(;iter != m_TimerItems.end();)
    {
        if((*iter).second.starttime++ < (*iter).second.interval)
        {
            ++iter;
            continue;
        }

        if((*iter).second.runCount != - 1 &&
           --(*iter).second.runCount <= 0)
        {
            try {
                // 调用Lua函数
                (*((*iter).second.callback))();
            } catch (const luabridge::LuaException& e) {
                printlog(LOG_LEVEL_ERROR,wxString::Format(wxT("CMainFrame::onProcessAllTimerEvent: %s") , e.what()).ToUTF8());
            }

            iter = m_TimerItems.erase(iter);
            continue;
        }

        try {
            // 调用Lua函数
            (*((*iter).second.callback))();
        } catch (const luabridge::LuaException& e) {
            printlog(LOG_LEVEL_ERROR,wxString::Format(wxT("CMainFrame::onProcessAllTimerEvent: %s") , e.what()).ToUTF8());
        }

        (*iter).second.starttime=0;
        ++iter;
    }
}

/// 处理网络二进制消息
void CMainFrame::OnProcessNetData(ClientInfo* client,int msgType,wxMemoryBuffer& data)
{
    ScriptManager::getSingleton().callLuaFunctionWithServerMessageCome(client->clientName.ToUTF8().data(),
                                                                       msgType,
                                                                       (const char*)data.GetData(),
                                                                       data.GetDataLen());
}

/// 处理一个新的连接到达
void CMainFrame::OnProcessConnectedNet(ClientInfo* client)
{
    ScriptManager::getSingleton().callLuaFunctionWithNetworkConnected(client->clientName.ToUTF8().data());
}
